package org.zhangyp.springbootsecurity.service;

import com.alibaba.fastjson.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.zhangyp.springbootsecurity.authentication.PhoneCodeAuthenticationToken;
import org.zhangyp.springbootsecurity.model.dto.LoginDTO;
import org.zhangyp.springbootsecurity.model.dto.PhoneCodeDTO;
import org.zhangyp.springbootsecurity.result.Result;
import org.zhangyp.springbootsecurity.util.JwtUtil;
import org.zhangyp.springbootsecurity.util.LoginCache;

/**
 * 登录service
 *
 * @author ypzhang
 * @since 2025/5/28
 */
@Service
public class AuthService {

    // 注入AuthenticationManagerBuilder，用于获得authenticationManager
    @Autowired
    private AuthenticationManagerBuilder authenticationManagerBuilder;

    public Result<String> login(LoginDTO loginDTO) {
        // 拿到前端传过来的用户名密码
        String username = loginDTO.getUsername();
        String password = loginDTO.getPassword();
        // 构建一个AuthenticationToken
        UsernamePasswordAuthenticationToken authenticationToken = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
        try {
            // 以下部分是因为我们屏蔽原先密码登录，自己实现密码登录，因此要模仿UsernamePasswordAuthenticationFilter处理流程
            // 使用authenticationManager认证
            Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
            // 成功返回登录成功
            if (authentication != null && authentication.isAuthenticated()) {
                // 保存用户信息
                SecurityContextHolder.getContext().setAuthentication(authentication);
                User user = (User) authentication.getPrincipal();
                String subject = JSONObject.toJSONString(user);
                System.out.println("subject = " + subject);
                String token = JwtUtil.createToken(subject, 1000 * 60 * 5L);
                return Result.success(token);
            }
        } catch (AuthenticationException e) {
            // 返回认证失败信息
            return Result.failed(e.getLocalizedMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed("未知错误");
        }
        return Result.failed("认证失败");
    }

    public Result<String> logout() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (StringUtils.hasText(token)) {
            // 加入黑名单
            LoginCache.BLACK_SET.add(token);
        }
        return Result.success("登出成功");
    }


    public Result<String> phoneCodeLogin(PhoneCodeDTO phoneCodeDTO) {
        String phone = phoneCodeDTO.getPhone();
        String code = phoneCodeDTO.getCode();
        // 构建一个AuthenticationToken
        PhoneCodeAuthenticationToken authenticationToken = new PhoneCodeAuthenticationToken(phone, code);
        try {
            // 使用authenticationManager认证
            Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
            // 成功返回登录成功
            if (authentication != null && authentication.isAuthenticated()) {
                // 保存用户信息
                SecurityContextHolder.getContext().setAuthentication(authentication);
                User user = (User) authentication.getPrincipal();
                String subject = JSONObject.toJSONString(user);
                System.out.println("subject = " + subject);
                String token = JwtUtil.createToken(subject, 1000 * 60 * 5L);
                return Result.success(token);
            }
        } catch (AuthenticationException e) {
            // 返回认证失败信息
            return Result.failed(e.getLocalizedMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed("未知错误");
        }
        return Result.failed("认证失败");
    }

}

